#include "drawingWidget.h"
#include "input.h"
#include "renderer.h"
#include "newDrawingButton.h"
#include "sliderButton.h"
#include "spriteMeshLoader.h"

//todo: change mouse pointer if drawingWidget is active


FlexGrid* DrawingWidget::flexGrid=NULL;
Brush*  DrawingWidget::brush=NULL;
Actor* DrawingWidget::grid=NULL;

string DrawingWidget::gridAxis="yAxis";;

DrawingWidget::DrawingWidget(){

name="drawingWidget";
tooltip="drawing widget";
//TODO: why do we need this variable here?
drawing=-1;
brushScale=1;
widgetLocation=Vector3f(0,0,0);
level = 0;
maxListItems=100;
}

DrawingWidget::~DrawingWidget(){

}

void DrawingWidget::setup(){

Button::setup();
bWidgetOpen=false;

brush=NULL;
flexGrid=NULL;

drawing=-1;

listDisplayMode=1;
listType.push_back("16NewDrawingButton");
listName.push_back("New Drawing");
listProp.push_back("NULL");
listIcon.push_back("icon_new");

/*
listType.push_back("12PencilButton");
listName.push_back("New Pencil Drawing");
listProp.push_back("NULL");
listIcon.push_back("icon_new");
*/

listType.push_back("19SelectDrawingButton");
listName.push_back("Select Drawing");
listProp.push_back("NULL");
listIcon.push_back("icon_brush");

listType.push_back("12SliderButton");               //todo: right click types in Value!
listName.push_back("Brush Size");
listProp.push_back("NULL");
listIcon.push_back("icon_flat");

listType.push_back("15ColorPickButton");
listName.push_back("Color");
listProp.push_back("NULL");
listIcon.push_back("icon_colorPad");

/*
listType.push_back("15LoadBrushButton");
listName.push_back("Load Brush");
listProp.push_back("NULL");
listIcon.push_back("icon_brushSize");
*/

listType.push_back("18ImportBitmapButton");
listName.push_back("Import Bitmap");
listProp.push_back("NULL");
listIcon.push_back("icon_load");

listType.push_back("17SaveDrawingButton");
listName.push_back("Save Drawing");
listProp.push_back("NULL");
listIcon.push_back("icon_save");

listType.push_back("17LoadDrawingButton");
listName.push_back("Load Drawing");
listProp.push_back("NULL");
listIcon.push_back("icon_load");

listType.push_back("22LoadDrawSkeletonButton");
listName.push_back("Load Skeleton");
listProp.push_back("NULL");
listIcon.push_back("icon_character");

/*
listType.push_back("18ConnectBrushButton");
listName.push_back("Connect Brush");
listProp.push_back("NULL");
listIcon.push_back("icon_advanced");
*/

listType.push_back("12AssignButton");
listName.push_back("merge Drawings");
listProp.push_back("NULL");
listIcon.push_back("icon_advanced");

listType.push_back("12AssignButton");
listName.push_back("scale x2");
listProp.push_back("NULL");
listIcon.push_back("icon_grow");

listType.push_back("12AssignButton");
listName.push_back("scale x0.5");
listProp.push_back("NULL");
listIcon.push_back("icon_shrink");

listType.push_back("15TextInputButton");
listName.push_back("make VBO");
listProp.push_back("NULL");
listIcon.push_back("icon_advanced");

widgetLocation=Vector3f(input->screenX/3,input->screenY-scale.y,0);
}


//now just pushing buttons down and out of the screen
void DrawingWidget::clickedLeft(){

    if (!bWidgetOpen){
        bWidgetOpen=true;
        for (uint i=0;i<listButton.size();i++)
            listButton[i]->location.y-=128;
        ListButton::clickedLeft();
        //assembleList();
    }
    else{
        for (uint i=0;i<listButton.size();i++)
            listButton[i]->location.y+=128;
        bWidgetOpen=false;
          if (brush)
            {
            brush->remove();
            brush=NULL;
            }
          if (flexGrid)
            {
            flexGrid->remove();
            flexGrid=NULL;
            }
          if (grid)
            destroyGrid();
    }

}

void DrawingWidget::trigger(Actor * other){

    if (other->name=="Brush Size"){
        SliderButton * sl;
        sl=(SliderButton*)other;
            if (brush){
                brush->scale.x=brushScale*(1.0-sl->sliderValue);
            }
    }

    if (other->name=="make VBO"){
        cout << "creating VBO..." << endl;
        renderer->spriteMeshLoader->saveSpriteMesh("resources/meshes/"+input->inputText+".spriteMesh",(SkeletalDrawing*)(brush->drawing));
        renderer->spriteMeshLoader->loadSpriteMesh("resources/meshes/"+input->inputText+".spriteMesh",input->inputText);
    }

    if (other->name=="merge Drawings"){
        //merge drawings here...
        cout << "merging selected drawings..." << endl;

        //check if we have only particleSystems selected!
        for (int i=0;i<(int)input->selectedActors.size();i++){
            ParticleSystem* myPS=dynamic_cast<ParticleSystem*>(input->selectedActors[i]);
            if (!myPS){
                cout << "wrong actors selected! Couldn't merge, sorry." << endl;
                return;
            }
        }

        //copy particles over
        ParticleSystem* receivePS;
        ParticleSystem* readPS;
        receivePS=dynamic_cast<ParticleSystem*>(input->selectedActors[0]);

        for (int i=1;i<(int)input->selectedActors.size();i++){
            readPS=dynamic_cast<ParticleSystem*>(input->selectedActors[i]);
            //copy values
            for (int i=0;i<(int)readPS->particles.size();i++){
                receivePS->particles.push_back(readPS->particles[i]);

                //calculate offset between particleSystems
                Vector4f readLoc=readPS->particles[i].location;
                //taking into account that we encode scale in the 4th location value
                float myScale=readLoc.w;
                readLoc.w=1.0;
                Vector4f locationOffset= readPS->baseMatrix * readLoc;
                locationOffset=receivePS->baseMatrix.inverse() * locationOffset;
                receivePS->particles[receivePS->particles.size()-1].location=locationOffset;
                receivePS->particles[receivePS->particles.size()-1].location.w=myScale;
            }
        }
    }

    if (other->name=="scale x2"){
        if (brush && brush->drawing){
            for (int i=0;i<(int)brush->drawing->particles.size();i++){
                brush->drawing->particles[i].location.w*=2.0;
            }
        }
    }

    if (other->name=="scale x0.5"){
        if (brush && brush->drawing){
            for (int i=0;i<(int)brush->drawing->particles.size();i++){
                brush->drawing->particles[i].location.w*=0.5;
            }
        }
    }

}

void DrawingWidget::placeButton(int buttonNumber, int drawPosition){

ListButton::placeButton(buttonNumber,drawPosition);
listButton[buttonNumber]->location+=widgetLocation-location;
listButton[buttonNumber]->tooltipOffset.x=2;
listButton[buttonNumber]->tooltipOffset.y=-listButton[buttonNumber]->scale.y/2 +2;

//special color for the "importBitmap" one...
if (buttonNumber==4)
    listButton[buttonNumber]->color=Vector4f(0.4,0.4,0.4,1.0);


listButton[buttonNumber]->bPermanent=true;
}

void DrawingWidget::deselect(int depth){

}


void DrawingWidget::createGrid(){

  //TODO: going through static Renderer is not good!
  Renderer::rendererInstance->pick(Input::inputInstance->mouseX, Input::inputInstance->mouseY);

  destroyGrid();

  grid= new Actor;
  grid->scale=Vector3f(10,10,10);
  grid->location=Input::inputInstance->mouse3D+Vector3f(0,grid->scale.y,0);


  grid->sceneShaderID="texture";

  grid->bTextured=true;
  grid->bUseShader=true;
  grid->bFullBright=true;

  grid->textureID="grid_solid";
  grid->name="grid";

  grid->drawType=DRAW_PLANE;

  //make sure our grid is not popping up menus when right clicking...
  //grid->menuType.empty();
  Renderer::rendererInstance->actorList.push_back(grid);
}

void DrawingWidget::createGrid(Vector3f offset){

  destroyGrid();

  Renderer::rendererInstance->pick(Input::inputInstance->mouseX, Input::inputInstance->mouseY);


  grid= new Actor;
  grid->location=Input::inputInstance->mouse3D+offset;
  grid->scale=Vector3f(5,5,5);

  grid->sceneShaderID="texture";

  grid->bTextured=true;
  grid->bUseShader=true;
  grid->bFullBright=true;

  grid->textureID="icon_grid";
  grid->location.x-=grid->scale.x*0.5;
  grid->name="grid";

  grid->drawType=DRAW_PLANE;

  //make sure our grid is not popping up menus when right clicking...
  grid->menuType.empty();

  Renderer::rendererInstance->actorList.push_back(grid);
}

void DrawingWidget::switchGridPlane(){

    Renderer::rendererInstance->pick(Input::inputInstance->mouseX,Input::inputInstance->mouseY);
    grid->location=Input::inputInstance->mouse3D;
    if (gridAxis=="zAxis"){
        grid->rotation=Vector3f(0,90,0);
        gridAxis="xAxis";
        }
    else if (gridAxis=="yAxis"){
        grid->rotation=Vector3f(90,0,0);
        gridAxis="zAxis";
        }
    else if (gridAxis=="xAxis"){
        grid->rotation=Vector3f(0,0,0);
        gridAxis="yAxis";
        }
}

void DrawingWidget::destroyGrid(){

    if (DrawingWidget::grid)
        {
        DrawingWidget::grid->remove();
        DrawingWidget::grid=NULL;
        }
}

void DrawingWidget::load(TiXmlElement* myInfo){

TiXmlHandle hRoot(0);
// save this for later
hRoot=TiXmlHandle(myInfo);

//***********************************************************************
//Assemble Actor List
//***********************************************************************


  TiXmlElement* element=hRoot.FirstChild( "Actor" ).Element();
  string myType;
  for( ; element!=NULL; element=element->NextSiblingElement())
	{
    cout << element->Value() << " " << element->GetText() <<endl;
	myType=element->GetText();
	Actor * A=renderer->actorInfo[myType].actorReference;
	A->create();
    A=renderer->actorList.back();
    //***********************************************************************
    //Fill up Properties
    //***********************************************************************
    A->load(element);
    A->setup();
    input->numParticles+=((ParticleSystem*)A)->particles.size();
    if (brush)
      brush->drawing=(ParticleSystem*) A;
    }
}
